#include "flv_protocol.hpp"
#include "server/rtmp/rtmp_message/rtmp_message.hpp"

using namespace mms;
int32_t FlvHeader::encode(uint8_t *data, size_t len)
{
    if (len < 9)
    {
        return 0;
    }

    data[0] = 'F';
    data[1] = 'L';
    data[2] = 'V';
    data[3] = 0x01;
    data[4] = 0x05; // 0x05
    data[5] = 0x00;
    data[6] = 0x00;
    data[7] = 0x00;
    data[8] = 0x09;
    return 9;
}

int32_t FlvHeader::decode(uint8_t *data, size_t len)
{
    if (len < 9)
    {
        return 0;
    }

    if (data[0] != 'F' || data[1] != 'L' || data[2] != 'V')
    {
        return -1;
    }
    version = data[3];
    flag = (Flags)(data[4]);
    if (data[8] != 0x09)
    {
        return -2;
    }
    return 9;
}

int32_t FlvTagHeader::encodeFromRtmpMessage(std::shared_ptr<RtmpMessage> msg, uint8_t *data, size_t len)
{
    uint8_t *start = data;
    if (len < 1)
    {
        return -1;
    }

    *data = msg->message_type_id_;
    len--;
    data++;

    if (len < 3)
    {
        return -2;
    }

    uint8_t *p = (uint8_t *)(&msg->payload_size_);
    data[0] = p[2];
    data[1] = p[1];
    data[2] = p[0];
    data += 3;
    len -= 3;
    if (len < 4)
    {
        return -3;
    }

    p = (uint8_t *)(&msg->timestamp_);
    data[0] = p[2];
    data[1] = p[1];
    data[2] = p[0];

    data[3] = p[3];
    data += 4;
    len -= 4;

    if (len < 3)
    {
        return -4;
    }
    data[0] = 0;
    data[1] = 0;
    data[2] = 0;
    data += 3;
    len -= 3;
    return data - start;
}

int32_t FlvTagHeader::encode(uint8_t *data, size_t len)
{
    uint8_t *data_start = (uint8_t *)data;
    if (len < 1)
    {
        return -1;
    }
    *data = (uint8_t)tag_type;
    data++;
    len--;

    if (len < 3)
    {
        return -2;
    }
    uint8_t *p = (uint8_t *)&data_size;
    data[0] = p[2];
    data[1] = p[1];
    data[2] = p[0];
    data += 3;
    len -= 3;

    if (len < 4)
    {
        return -3;
    }
    p = (uint8_t *)&timestamp;
    data[0] = p[2];
    data[1] = p[1];
    data[2] = p[0];
    data[3] = p[3];
    data += 4;
    len -= 4;

    if (len < 3)
    {
        return -4;
    }
    p = (uint8_t *)&stream_id;
    data[0] = p[2];
    data[1] = p[1];
    data[2] = p[0];
    data += 3;
    return data - data_start;
}

int32_t FlvTagHeader::decode(const uint8_t *data, size_t len)
{
    uint8_t *data_start = (uint8_t *)data;
    if (len < 1)
    {
        return 0;
    }
    tag_type = data[0];
    len--;
    data++;

    if (len < 3)
    {
        return 0;
    }
    // uint8_t *p = (uint8_t*)&data_size;
    uint8_t t[4] = {0};
    memcpy(t + 1, data, 3);
    data_size = ntohl(*(uint32_t *)t);
    data += 3;
    len -= 3;

    if (len < 4)
    {
        return 0;
    }
    memset(t, 0, 4);
    memcpy(t + 1, data, 3);
    timestamp = ntohl(*(uint32_t *)t);
    timestamp |= ((uint32_t)data[3]) << 24;
    data += 4;
    len -= 4;

    if (len < 3)
    {
        return 0;
    }

    uint8_t *p = (uint8_t *)&stream_id;
    p[0] = data[2];
    p[1] = data[1];
    p[2] = data[0];
    data += 3;
    return data - data_start;
}